#ifndef AVIATION_DATABASE_H
#define AVIATION_DATABASE_H

#include <set>
#include <string>

#include "flight.h"
#include "customer.h"
#include "reservation.h"

#include <boost/serialization/nvp.hpp>

namespace aviation
{

/// This is a templated data structure that forms a simple shell around the std::set class.
template <class Data>
class Database
{
public:

	/// A simple functor that allows us to store anything with operator<() defined in a std::set.
	struct DataComparator { bool operator()(const Data& d1, const Data& d2)	{ return d1 < d2; }};

	typedef typename std::set<Data, DataComparator> DataSet;
	typedef typename DataSet::iterator Iterator;

	/// Default constructor, creates an empty database.
	Database();
	/// Trivial destructor.
	~Database();

	/// Adds the given data to the database.
	/// \param data The data to be added.
	/// \returns The database, with the data added.
	Database& AddData(const Data& data);

	/// Removes the given data from the database.
	/// \param data The data to be removed.
	/// \returns The database, with the data removed.
	Database& RemoveData(const Data& data);

	/// Finds out if the given data is contained in the database.
	/// \param data The data to be searched for in the database.
	/// \returns True if the data is in the database, or false if it is not.
	bool ContainsData(const Data& data);

	/// Returns an iterator referring to the first object in the database.
	Iterator Begin();
	/// Returns an iterator pointing to the end of the database- the iterator after the last valid entry.
	Iterator End();

	/// Returns the number of entries in the database.
	const size_t Size() const;

	/// Serialization (file I-O) function.
	/// \param ar A boost::archive formatter type.
	/// \param version The file version.
	template <class Archive>
	void serialize(Archive& ar, unsigned int version);

private:

	DataSet m_dataSet;
};

template <class Data>
Database<Data>::Database()
{

}

template <class Data>
Database<Data>::~Database()
{

}

template <class Data>
Database<Data>& Database<Data>::AddData(const Data& data)
{
	m_dataSet.insert(data);
	return *this;
}

template <class Data>
Database<Data>& Database<Data>::RemoveData(const Data& data)
{
	Iterator position = m_dataSet.find(data);

	if(position != End()) m_dataSet.erase(position);

	return *this;
}

template <class Data>
bool Database<Data>::ContainsData(const Data& data)
{
	return m_dataSet.find(data) != m_dataSet.end();
}

template <class Data>
typename Database<Data>::Iterator Database<Data>::Begin()
{
	return m_dataSet.begin();
}

template <class Data>
typename Database<Data>::Iterator Database<Data>::End()
{
	return m_dataSet.end();
}

template <class Data>
typename const std::size_t Database<Data>::Size() const
{
	return m_dataSet.size();
}

template <class Data>
template <class Archive>
void Database<Data>::serialize(Archive& ar, unsigned int version)
{
	ar & BOOST_SERIALIZATION_NVP(m_dataSet);
}

} // namespace aviation

#endif // AVIATION_DATABASE_H 